package com.iplant.aps.serviceimpl.dao.sfc;

import com.iplant.aps.service.mesenum.BFCMessageType;
import com.iplant.aps.service.mesenum.BPMEventModule;
import com.iplant.aps.service.mesenum.MESDBSource;
import com.iplant.aps.service.mesenum.MESException;
import com.iplant.aps.service.po.OutResult;
import com.iplant.aps.service.po.ServiceResult;
import com.iplant.aps.service.po.bfc.BFCMessage;
import com.iplant.aps.service.po.bms.BMSEmployee;
import com.iplant.aps.service.po.bpm.BPMTaskBase;
import com.iplant.aps.service.po.sfc.SFCBatchBOMTaskBPM;
import com.iplant.aps.service.po.sfc.SFCBatchBOMTaskBPMItem;
import com.iplant.aps.service.utils.CloneTool;
import com.iplant.aps.service.utils.StringUtils;
import com.iplant.aps.serviceimpl.CoreServiceImpl;
import com.iplant.aps.serviceimpl.dao.BaseDAO;
import com.iplant.aps.serviceimpl.dao.TaskBaseDAO;
import com.iplant.aps.serviceimpl.utils.aps.APSConstans;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

public class SFCBatchBOMTaskBPMDAO extends BaseDAO implements TaskBaseDAO {

    private static final Logger logger = LoggerFactory.getLogger(SFCBatchBOMTaskBPMDAO.class);

    private static SFCBatchBOMTaskBPMDAO Instance = null;

    private SFCBatchBOMTaskBPMDAO() {
        super();
    }

    public static SFCBatchBOMTaskBPMDAO getInstance() {
        if (Instance == null)
            Instance = new SFCBatchBOMTaskBPMDAO();
        return Instance;
    }

    /**
     * 添加或修改
     */
    public SFCBatchBOMTaskBPM Update(BMSEmployee wLoginUser, SFCBatchBOMTaskBPM wSFCBatchBOMTaskBPM,
                                     OutResult<Integer> wErrorCode) {
        try {
            ServiceResult<String> wInstance = this.GetDataBaseName(wLoginUser.getCompanyID(), MESDBSource.Basic,
                    wLoginUser.getID(), 0);
            wErrorCode.set(wInstance.ErrorCode);
            if (wErrorCode.Result != 0) {
                return wSFCBatchBOMTaskBPM;
            }

            if (wSFCBatchBOMTaskBPM == null)
                return null;

            String wSQL = "";
            if (wSFCBatchBOMTaskBPM.getID() <= 0) {
                wSQL = MessageFormat.format("INSERT INTO {0}.sfc_batchbomtaskbpm(Code,FlowType,FlowID,UpFlowID," +
                                "FollowerID,Status,StatusText,CreateTime,SubmitTime,PlanNumber,DescriptionInfo," +
                                "SendStatus,SendStatusText,ImageUrl,SourceType,ProductID,LineID) VALUES(:Code," +
                                ":FlowType,:FlowID," +
                                ":UpFlowID,:FollowerID,:Status,:StatusText,:CreateTime,:SubmitTime,:PlanNumber," +
                                ":DescriptionInfo,:SendStatus,:SendStatusText,:ImageUrl,:SourceType,:ProductID," +
                                ":LineID);",
                        wInstance.Result);
            } else {
                wSQL = MessageFormat.format("UPDATE {0}.sfc_batchbomtaskbpm SET Code = :Code,FlowType = :FlowType," +
                                "FlowID = :FlowID,UpFlowID = :UpFlowID,FollowerID = :FollowerID,Status = :Status," +
                                "StatusText = :StatusText,CreateTime = :CreateTime,SubmitTime = now()," +
                                "PlanNumber" +
                                " = :PlanNumber,DescriptionInfo = :DescriptionInfo,SendStatus = :SendStatus," +
                                "SendStatusText = :SendStatusText,ImageUrl = :ImageUrl,SourceType = :SourceType," +
                                "ProductID=:ProductID,LineID=:LineID WHERE" +
                                " " +
                                "ID = :ID;",
                        wInstance.Result);
            }

            wSQL = this.DMLChange(wSQL);

            Map<String, Object> wParamMap = new HashMap<>();

            wParamMap.put("ID", wSFCBatchBOMTaskBPM.ID);
            wParamMap.put("Code", wSFCBatchBOMTaskBPM.Code);
            wParamMap.put("FlowType", wSFCBatchBOMTaskBPM.FlowType);
            wParamMap.put("FlowID", wSFCBatchBOMTaskBPM.FlowID);
            wParamMap.put("UpFlowID", wSFCBatchBOMTaskBPM.UpFlowID);
            wParamMap.put("FollowerID", StringUtils.Join(",", wSFCBatchBOMTaskBPM.FollowerID));
            wParamMap.put("Status", wSFCBatchBOMTaskBPM.Status);
            wParamMap.put("StatusText", wSFCBatchBOMTaskBPM.StatusText);
            wParamMap.put("CreateTime", wSFCBatchBOMTaskBPM.CreateTime);
            wParamMap.put("SubmitTime", wSFCBatchBOMTaskBPM.SubmitTime);
            wParamMap.put("PlanNumber", wSFCBatchBOMTaskBPM.PlanNumber);
            wParamMap.put("DescriptionInfo", wSFCBatchBOMTaskBPM.DescriptionInfo);
            wParamMap.put("SendStatus", wSFCBatchBOMTaskBPM.SendStatus);
            wParamMap.put("SendStatusText", wSFCBatchBOMTaskBPM.SendStatusText);
            wParamMap.put("ImageUrl", wSFCBatchBOMTaskBPM.ImageUrl);
            wParamMap.put("SourceType", wSFCBatchBOMTaskBPM.SourceType);
            wParamMap.put("ProductID", wSFCBatchBOMTaskBPM.ProductID);
            wParamMap.put("LineID", wSFCBatchBOMTaskBPM.LineID);

            KeyHolder keyHolder = new GeneratedKeyHolder();
            SqlParameterSource wSqlParameterSource = new MapSqlParameterSource(wParamMap);

            shrisJdbcTemplate.update(wSQL, wSqlParameterSource, keyHolder);

            if (wSFCBatchBOMTaskBPM.getID() <= 0) {
                wSFCBatchBOMTaskBPM.ID = Objects.requireNonNull(keyHolder.getKey()).intValue();
            } else {
                wSFCBatchBOMTaskBPM.ID = wSFCBatchBOMTaskBPM.getID();
            }
        } catch (Exception ex) {
            wErrorCode.set(MESException.DBSQL.getValue());
            logger.error(ex.toString());
        }
        return wSFCBatchBOMTaskBPM;
    }

    /**
     * 删除集合
     */
    public ServiceResult<Integer> DeleteList(BMSEmployee wLoginUser, List<SFCBatchBOMTaskBPM> wList,
                                             OutResult<Integer> wErrorCode) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            ServiceResult<String> wInstance = this.GetDataBaseName(wLoginUser.getCompanyID(), MESDBSource.Basic,
                    wLoginUser.getID(), 0);
            wErrorCode.set(wInstance.ErrorCode);
            if (wErrorCode.Result != 0) {
                return wResult;
            }

            if (wList == null || wList.size() <= 0)
                return wResult;

            List<String> wIDList = new ArrayList<>();
            for (SFCBatchBOMTaskBPM wItem : wList) {
                wIDList.add(String.valueOf(wItem.ID));
            }
            String wSql = MessageFormat.format("delete from {1}.sfc_batchbomtaskbpm WHERE ID IN({0}) ;",
                    String.join(",", wIDList), wInstance.Result);
            this.ExecuteSqlTransaction(wSql);
        } catch (Exception ex) {
            wErrorCode.set(MESException.DBSQL.getValue());
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 查单条
     */
    public SFCBatchBOMTaskBPM SelectByID(BMSEmployee wLoginUser, int wID, OutResult<Integer> wErrorCode) {
        SFCBatchBOMTaskBPM wResult = new SFCBatchBOMTaskBPM();
        try {
            ServiceResult<String> wInstance = this.GetDataBaseName(wLoginUser.getCompanyID(), MESDBSource.Basic,
                    wLoginUser.getID(), 0);
            wErrorCode.set(wInstance.ErrorCode);
            if (wErrorCode.Result != 0) {
                return wResult;
            }

            List<SFCBatchBOMTaskBPM> wList = SelectList(wLoginUser, wID, "", -1, -1, -1, null, null, wErrorCode);
            if (wList == null || wList.size() != 1)
                return wResult;
            wResult = wList.get(0);
            wResult.SFCBatchBOMTaskBPMItemList = SFCBatchBOMTaskBPMItemDAO.getInstance().SelectList(wLoginUser, -1,
                    wResult.ID, -1, -1, -1, -1, "", wErrorCode);
        } catch (Exception e) {
            wErrorCode.set(MESException.DBSQL.getValue());
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 条件查询集合
     */
    public List<SFCBatchBOMTaskBPM> SelectList(BMSEmployee wLoginUser, int wID, String wCode, int wUpFlowID,
                                               int wStatus, int wSendStatus, Calendar wStartTime, Calendar wEndTime,
                                               OutResult<Integer> wErrorCode) {
        List<SFCBatchBOMTaskBPM> wResultList = new ArrayList<>();
        try {
            ServiceResult<String> wInstance = this.GetDataBaseName(wLoginUser.getCompanyID(), MESDBSource.Basic,
                    wLoginUser.getID(), 0);
            wErrorCode.set(wInstance.ErrorCode);
            if (wErrorCode.Result != 0) {
                return wResultList;
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);
            if (wStartTime == null) {
                wStartTime = wBaseTime;
            }
            if (wEndTime == null) {
                wEndTime = wBaseTime;
            }
            if (wStartTime.compareTo(wEndTime) > 0) {
                return wResultList;
            }

            String wSQL = MessageFormat.format(
                    "SELECT * FROM {0}.sfc_batchbomtaskbpm WHERE  1=1  and ( :wID <= 0 or :wID = ID ) and ( :wCode is" +
                            " null or :wCode = '''' or :wCode = Code ) and ( :wUpFlowID <= 0 or :wUpFlowID = UpFlowID" +
                            " " +
                            ") and ( :wStatus < 0 or :wStatus = Status )and ( :wStartTime <=str_to_date" +
                            "(''2010-01-01'', ''%Y-%m-%d'')  or :wStartTime <=  SubmitTime ) and ( :wEndTime " +
                            "<=str_to_date(''2010-01-01'', ''%Y-%m-%d'')  or :wEndTime >=  CreateTime ) and ( " +
                            ":wSendStatus <= 0 or :wSendStatus = SendStatus );",
                    wInstance.Result);

            Map<String, Object> wParamMap = new HashMap<>();

            wParamMap.put("wID", wID);
            wParamMap.put("wCode", wCode);
            wParamMap.put("wUpFlowID", wUpFlowID);
            wParamMap.put("wStatus", wStatus);
            wParamMap.put("wSendStatus", wSendStatus);
            wParamMap.put("wStartTime", wStartTime);
            wParamMap.put("wEndTime", wEndTime);

            wSQL = this.DMLChange(wSQL);

            List<Map<String, Object>> wQueryResult = shrisJdbcTemplate.queryForList(wSQL, wParamMap);

            SetValue(wResultList, wQueryResult);
        } catch (Exception ex) {
            wErrorCode.set(MESException.DBSQL.getValue());
            logger.error(ex.toString());
        }
        return wResultList;
    }

    /**
     * 条件查询集合
     */
    public List<SFCBatchBOMTaskBPM> SelectList(BMSEmployee wLoginUser, List<Integer> wTaskIDList,
                                               List<Integer> wStatusList, List<Integer> wNotStatusList,
                                               Calendar wStartTime, Calendar wEndTime,
                                               OutResult<Integer> wErrorCode) {
        List<SFCBatchBOMTaskBPM> wResultList = new ArrayList<>();
        try {
            ServiceResult<String> wInstance = this.GetDataBaseName(wLoginUser.getCompanyID(), MESDBSource.Basic,
                    wLoginUser.getID(), 0);
            wErrorCode.set(wInstance.ErrorCode);
            if (wErrorCode.Result != 0) {
                return wResultList;
            }

            if (wTaskIDList == null)
                wTaskIDList = new ArrayList<>();
            if (wStatusList == null)
                wStatusList = new ArrayList<>();
            if (wNotStatusList == null)
                wNotStatusList = new ArrayList<>();

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);
            if (wStartTime == null) {
                wStartTime = wBaseTime;
            }
            if (wEndTime == null) {
                wEndTime = wBaseTime;
            }
            if (wStartTime.compareTo(wEndTime) > 0) {
                return wResultList;
            }

            String wSQL = MessageFormat.format(
                    "SELECT * FROM {0}.sfc_batchbomtaskbpm WHERE  1=1 and (:wTaskID=null or :wTaskID='''' or ID in " +
                            "({1}))" +
                            " and (:wStatus=null or :wStatus='''' or Status in ({2}))" +
                            " and (:wNotStatus=null or :wNotStatus='''' or Status not in ({3}))" +
                            " and ( :wStartTime <=str_to_date" +
                            "(''2010-01-01'', ''%Y-%m-%d'')  or :wStartTime <=  SubmitTime ) and ( :wEndTime " +
                            "<=str_to_date(''2010-01-01'', ''%Y-%m-%d'')  or :wEndTime >=  CreateTime );",
                    wInstance.Result, wTaskIDList.size() <= 0 ? "0" : StringUtils.Join(",", wTaskIDList),
                    wStatusList.size() <= 0 ? "0" : StringUtils.Join(",", wStatusList), wNotStatusList.size() <= 0 ?
                            "0" :
                            StringUtils.Join(",", wNotStatusList));

            Map<String, Object> wParamMap = new HashMap<>();

            wParamMap.put("wTaskID", StringUtils.Join(",", wTaskIDList));
            wParamMap.put("wStatus", StringUtils.Join(",", wStatusList));
            wParamMap.put("wNotStatus", StringUtils.Join(",", wNotStatusList));
            wParamMap.put("wStartTime", wStartTime);
            wParamMap.put("wEndTime", wEndTime);

            wSQL = this.DMLChange(wSQL);

            List<Map<String, Object>> wQueryResult = shrisJdbcTemplate.queryForList(wSQL, wParamMap);

            SetValue(wResultList, wQueryResult);
        } catch (Exception ex) {
            wErrorCode.set(MESException.DBSQL.getValue());
            logger.error(ex.toString());
        }
        return wResultList;
    }

    /**
     * 条件查询集合
     */
    public List<SFCBatchBOMTaskBPM> SelectList(BMSEmployee wLoginUser, List<Integer> wTaskIDList, Calendar wStartTime
            , Calendar wEndTime,
                                               OutResult<Integer> wErrorCode) {
        List<SFCBatchBOMTaskBPM> wResultList = new ArrayList<>();
        try {
            ServiceResult<String> wInstance = this.GetDataBaseName(wLoginUser.getCompanyID(), MESDBSource.Basic,
                    wLoginUser.getID(), 0);
            wErrorCode.set(wInstance.ErrorCode);
            if (wErrorCode.Result != 0) {
                return wResultList;
            }

            if (wTaskIDList == null || wTaskIDList.size() <= 0) {
                return wResultList;
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);
            if (wStartTime == null) {
                wStartTime = wBaseTime;
            }
            if (wEndTime == null) {
                wEndTime = wBaseTime;
            }
            if (wStartTime.compareTo(wEndTime) > 0) {
                return wResultList;
            }

            String wSQL = MessageFormat.format(
                    "SELECT * FROM {0}.sfc_batchbomtaskbpm WHERE  1=1  and ( ID in ({1}) ) " +
                            "and ( :wStartTime <=str_to_date (''2010-01-01'', ''%Y-%m-%d'')  or :wStartTime <=  " +
                            "SubmitTime ) " +
                            "and ( :wEndTime <=str_to_date(''2010-01-01'', ''%Y-%m-%d'')  or :wEndTime >=  CreateTime" +
                            " ) ;",
                    wInstance.Result, StringUtils.Join(",", wTaskIDList));

            Map<String, Object> wParamMap = new HashMap<>();

            wParamMap.put("wStartTime", wStartTime);
            wParamMap.put("wEndTime", wEndTime);

            wSQL = this.DMLChange(wSQL);

            List<Map<String, Object>> wQueryResult = shrisJdbcTemplate.queryForList(wSQL, wParamMap);

            SetValue(wResultList, wQueryResult);
        } catch (Exception ex) {
            wErrorCode.set(MESException.DBSQL.getValue());
            logger.error(ex.toString());
        }
        return wResultList;
    }

    /**
     * 获取最新的编码
     */
    public synchronized String GetNewCode(BMSEmployee wLoginUser, OutResult<Integer> wErrorCode) {
        String wResult = "";
        try {
            ServiceResult<String> wInstance = this.GetDataBaseName(wLoginUser, MESDBSource.Basic, 0);
            wErrorCode.set(wInstance.ErrorCode);
            if (wErrorCode.Result != 0) {
                return wResult;
            }

            String wSQL = StringUtils.Format(
                    "SELECT Code FROM {0}.sfc_batchbomtaskbpm WHERE id IN( SELECT MAX(ID) FROM {0}" +
                            ".sfc_batchbomtaskbpm);",
                    wInstance.Result);

            Map<String, Object> wParamMap = new HashMap<>();

            wSQL = this.DMLChange(wSQL);

            List<Map<String, Object>> wQueryResult = shrisJdbcTemplate.queryForList(wSQL, wParamMap);

            int wNumber = 1;
            int wMonth = Calendar.getInstance().get(Calendar.MONTH) + 1;
            for (Map<String, Object> wReader : wQueryResult) {
                String wDemandNo = StringUtils.parseString(wReader.get("Code"));
                int wCodeMonth = StringUtils.parseInt(wDemandNo.substring(8, 10));
                if (wMonth > wCodeMonth)
                    wNumber = 1;
                else
                    wNumber = StringUtils.parseInt(wDemandNo.substring(10)) + 1;
            }

            wResult = StringUtils.Format("BOCR{0}{1}{2}", String.valueOf(Calendar.getInstance().get(Calendar.YEAR)),
                    String.format("%02d", Calendar.getInstance().get(Calendar.MONTH) + 1),
                    String.format("%04d", wNumber));
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    private void SetValue(List<SFCBatchBOMTaskBPM> wResultList, List<Map<String, Object>> wQueryResult) {
        try {
            for (Map<String, Object> wReader : wQueryResult) {
                SFCBatchBOMTaskBPM wItem = new SFCBatchBOMTaskBPM();

                wItem.ID = StringUtils.parseInt(wReader.get("ID"));
                wItem.Code = StringUtils.parseString(wReader.get("Code"));
                wItem.FlowType = StringUtils.parseInt(wReader.get("FlowType"));
                wItem.FlowID = StringUtils.parseInt(wReader.get("FlowID"));
                wItem.UpFlowID = StringUtils.parseInt(wReader.get("UpFlowID"));
                wItem.FollowerID = StringUtils.parseIntList(StringUtils.parseString(wReader.get("FollowerID")).split(
                        ","));
                wItem.Status = StringUtils.parseInt(wReader.get("Status"));
                wItem.StatusText = StringUtils.parseString(wReader.get("StatusText"));
                wItem.CreateTime = StringUtils.parseCalendar(wReader.get("CreateTime"));
                wItem.SubmitTime = StringUtils.parseCalendar(wReader.get("SubmitTime"));
                wItem.PlanNumber = StringUtils.parseInt(wReader.get("PlanNumber"));
                wItem.DescriptionInfo = StringUtils.parseString(wReader.get("DescriptionInfo"));
                wItem.SendStatus = StringUtils.parseInt(wReader.get("SendStatus"));
                wItem.SendStatusText = StringUtils.parseString(wReader.get("SendStatusText"));
                wItem.ImageUrl = StringUtils.parseString(wReader.get("ImageUrl"));
                wItem.SourceType = StringUtils.parseInt(wReader.get("SourceType"));
                wItem.ProductID = StringUtils.parseInt(wReader.get("ProductID"));
                wItem.ProductNo = APSConstans.GetFPCProductNo(wItem.ProductID);
                wItem.LineID = StringUtils.parseInt(wReader.get("LineID"));
                wItem.LineName = APSConstans.GetFMCLineName(wItem.LineID);

                wItem.UpFlowName = APSConstans.GetBMSEmployeeName(wItem.UpFlowID);

                wResultList.add(wItem);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public List<BPMTaskBase> BPM_GetUndoTaskList(BMSEmployee wLoginUser, int wResponsorID,
                                                 OutResult<Integer> wErrorCode) {
        List<SFCBatchBOMTaskBPM> wResult = new ArrayList<>();
        try {
            // 获取所有任务消息
            List<BFCMessage> wMessageList = CoreServiceImpl.getInstance()
                    .BFC_GetMessageList(wLoginUser, wLoginUser.getID(), BPMEventModule.BatchOccasionNCR.getValue(), -1,
                            BFCMessageType.Task.getValue(), 0, -1, null, null)
                    .List(BFCMessage.class);
            wMessageList.addAll(CoreServiceImpl.getInstance().BFC_GetMessageList(wLoginUser, wLoginUser.getID(),
                            BPMEventModule.BatchOccasionNCR.getValue(), -1, BFCMessageType.Task.getValue(), 1, -1, null,
                            null)
                    .List(BFCMessage.class));
            wMessageList.addAll(CoreServiceImpl.getInstance().BFC_GetMessageList(wLoginUser, wLoginUser.getID(),
                            BPMEventModule.BatchOccasionNCR.getValue(), -1, BFCMessageType.Task.getValue(), 2, -1, null,
                            null)
                    .List(BFCMessage.class));

            List<Integer> wTaskIDList = wMessageList.stream().map(p -> (int) p.MessageID).distinct()
                    .collect(Collectors.toList());

            // 所有未完成的任务
            Map<Integer, SFCBatchBOMTaskBPM> wTaskMap = new HashMap<>();
            if (wTaskIDList.size() > 0) {
                List<SFCBatchBOMTaskBPM> wMTCTaskListTemp = this.SelectList(wLoginUser, wTaskIDList, null, null,
                        wErrorCode);

                wTaskMap = wMTCTaskListTemp.stream().collect(Collectors.toMap(p -> p.ID, p -> p, (o1, o2) -> o1));

            }
            SFCBatchBOMTaskBPM wTaskTemp;
            for (BFCMessage wBFCMessage : wMessageList) {
                if (!wTaskMap.containsKey((int) wBFCMessage.getMessageID()))
                    continue;

                wTaskTemp = CloneTool.Clone(wTaskMap.get((int) wBFCMessage.getMessageID()), SFCBatchBOMTaskBPM.class);
                wTaskTemp.StepID = wBFCMessage.getStepID();
                wResult.add(wTaskTemp);
            }

            wResult.sort(Comparator.comparing(SFCBatchBOMTaskBPM::getSubmitTime).reversed());
            // 剔除任务状态为0的任务（废弃任务）
            if (wResult.size() > 0) {
                wResult = wResult.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }
        } catch (Exception e) {
            wErrorCode.set(MESException.Exception.getValue());
            logger.error(e.toString());
        }
        return new ArrayList<>(wResult);
    }

    @Override
    public List<BPMTaskBase> BPM_GetDoneTaskList(BMSEmployee wLoginUser, int wResponsorID, Calendar wStartTime,
                                                 Calendar wEndTime, OutResult<Integer> wErrorCode) {
        List<SFCBatchBOMTaskBPM> wResult = new ArrayList<>();
        wErrorCode.set(0);
        try {
            List<SFCBatchBOMTaskBPM> wTaskList;
            // 获取所有任务消息
            List<BFCMessage> wMessageList = CoreServiceImpl.getInstance()
                    .BFC_GetMessageList(wLoginUser, wLoginUser.getID(), BPMEventModule.BatchOccasionNCR.getValue(), -1,
                            BFCMessageType.Task.getValue(), 3, -1, wStartTime, wEndTime)
                    .List(BFCMessage.class);
            wMessageList
                    .addAll(CoreServiceImpl.getInstance()
                            .BFC_GetMessageList(wLoginUser, wLoginUser.getID(),
                                    BPMEventModule.BatchOccasionNCR.getValue(),
                                    -1, BFCMessageType.Task.getValue(), 4, -1, wStartTime, wEndTime)
                            .List(BFCMessage.class));

            List<Integer> wTaskIDList = wMessageList.stream().map(p -> (int) p.MessageID).distinct()
                    .collect(Collectors.toList());

            if (wTaskIDList.size() <= 0) {
                return new ArrayList<>(wResult);
            }

            wTaskList = this.SelectList(wLoginUser, wTaskIDList, wStartTime, wEndTime, wErrorCode);

            wTaskList.sort(Comparator.comparing(SFCBatchBOMTaskBPM::getSubmitTime).reversed());

            wResult = wTaskList;
            // 剔除任务状态为0的任务（废弃任务）
            if (wResult.size() > 0) {
                wResult = wResult.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return new ArrayList<>(wResult);
    }

    @Override
    public List<BPMTaskBase> BPM_GetSendTaskList(BMSEmployee wLoginUser, int wResponsorID, Calendar wStartTime,
                                                 Calendar wEndTime, OutResult<Integer> wErrorCode) {
        List<SFCBatchBOMTaskBPM> wResult = new ArrayList<>();
        try {
            wResult = this.SelectList(wLoginUser, -1, "", wResponsorID, -1, -1, wStartTime, wEndTime, wErrorCode);
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return new ArrayList<>(wResult);
    }

    @Override
    public BPMTaskBase BPM_UpdateTask(BMSEmployee wLoginUser, BPMTaskBase wTask, OutResult<Integer> wErrorCode) {
        BPMTaskBase wResult = new BPMTaskBase();
        try {
            wResult = this.Update(wLoginUser, (SFCBatchBOMTaskBPM) wTask, wErrorCode);

            // 保存bom子项
            if (((SFCBatchBOMTaskBPM) wTask).SFCBatchBOMTaskBPMItemList != null
                    && ((SFCBatchBOMTaskBPM) wTask).SFCBatchBOMTaskBPMItemList.size() > 0) {
                List<SFCBatchBOMTaskBPMItem> wItemList =
                        SFCBatchBOMTaskBPMItemDAO.getInstance().SelectList(wLoginUser, -1, wTask.ID, -1,
                                -1, -1, -1, "", wErrorCode);
                List<SFCBatchBOMTaskBPMItem> wDeList =
                        wItemList.stream().filter(p -> ((SFCBatchBOMTaskBPM) wTask).SFCBatchBOMTaskBPMItemList.stream().
                                noneMatch(q -> q.PartID == p.PartID && q.PartPointID == p.PartPointID
                                        && q.MaterialID == p.MaterialID)).collect(Collectors.toList());
                SFCBatchBOMTaskBPMItemDAO.getInstance().DeleteList(wLoginUser, wDeList, wErrorCode);

                for (SFCBatchBOMTaskBPMItem wSFCBatchBOMTaskBPMItem :
                        ((SFCBatchBOMTaskBPM) wTask).SFCBatchBOMTaskBPMItemList) {
                    wSFCBatchBOMTaskBPMItem.SFCBatchBOMTaskID = wResult.ID;
                    SFCBatchBOMTaskBPMItemDAO.getInstance().Update(wLoginUser, wSFCBatchBOMTaskBPMItem, wErrorCode);
                }
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public BPMTaskBase BPM_GetTaskInfo(BMSEmployee wLoginUser, int wTaskID, String wCode,
                                       OutResult<Integer> wErrorCode) {
        SFCBatchBOMTaskBPM wResult = new SFCBatchBOMTaskBPM();
        try {
            ServiceResult<String> wInstance = this.GetDataBaseName(wLoginUser, MESDBSource.APS, 0);
            wErrorCode.set(wInstance.ErrorCode);
            if (wErrorCode.Result != 0) {
                return wResult;
            }

            List<SFCBatchBOMTaskBPM> wList = this.SelectList(wLoginUser, wTaskID, wCode, -1, -1, -1, null, null,
                    wErrorCode);
            if (wList == null || wList.size() != 1)
                return wResult;
            wResult = wList.get(0);

            wResult.SFCBatchBOMTaskBPMItemList = SFCBatchBOMTaskBPMItemDAO.getInstance().SelectList(wLoginUser, -1,
                    wTaskID, -1, -1, -1, -1, "", wErrorCode);
        } catch (Exception e) {
            wErrorCode.set(MESException.DBSQL.getValue());
            logger.error(e.toString());
        }
        return wResult;
    }

    public List<Integer> SFC_QueryBatchBOMTaskPartList(BMSEmployee wLoginUser, int wProductID, int wLineID,
                                                       OutResult<Integer> wErrorCode) {
        List<Integer> wResult = new ArrayList<>();
        try {
            ServiceResult<String> wInstance = this.GetDataBaseName(wLoginUser.getCompanyID(), MESDBSource.Basic,
                    wLoginUser.getID(), 0);
            wErrorCode.set(wInstance.ErrorCode);
            if (wErrorCode.Result != 0) {
                return wResult;
            }

            String wSQL = StringUtils.Format("SELECT DISTINCT PartID FROM {0}.fpc_routepart WHERE routeid IN " +
                            "(SELECT ID FROM {0}.fpc_route WHERE lineid=:lineid AND productid=:productid AND " +
                            "IsStandard=1);",
                    wInstance.Result);

            Map<String, Object> wParamMap = new HashMap<>();

            wParamMap.put("lineid", wLineID);
            wParamMap.put("productid", wProductID);

            wSQL = this.DMLChange(wSQL);

            List<Map<String, Object>> wQueryResult = shrisJdbcTemplate.queryForList(wSQL, wParamMap);

            for (Map<String, Object> wReader : wQueryResult) {
                int wPartID = StringUtils.parseInt(wReader.get("PartID"));
                wResult.add(wPartID);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    public List<Integer> SFC_QueryBatchBOMTaskPartPointList(BMSEmployee wLoginUser, int wProductID, int wLineID,
                                                            int wPartID, OutResult<Integer> wErrorCode) {
        List<Integer> wResult = new ArrayList<>();
        try {
            ServiceResult<String> wInstance = this.GetDataBaseName(wLoginUser.getCompanyID(), MESDBSource.Basic,
                    wLoginUser.getID(), 0);
            wErrorCode.set(wInstance.ErrorCode);
            if (wErrorCode.Result != 0) {
                return wResult;
            }

            String wSQL = StringUtils.Format("SELECT DISTINCT PartPointID FROM {0}.fpc_routepartpoint WHERE " +
                            "routeid IN (SELECT ID FROM {0}.fpc_route WHERE lineid=:lineid AND productid=:productid " +
                            "AND " +
                            "IsStandard=1) AND PartID=:PartID;",
                    wInstance.Result);

            Map<String, Object> wParamMap = new HashMap<>();

            wParamMap.put("lineid", wLineID);
            wParamMap.put("productid", wProductID);
            wParamMap.put("PartID", wPartID);

            wSQL = this.DMLChange(wSQL);

            List<Map<String, Object>> wQueryResult = shrisJdbcTemplate.queryForList(wSQL, wParamMap);

            for (Map<String, Object> wReader : wQueryResult) {
                int wPartPointID = StringUtils.parseInt(wReader.get("PartPointID"));
                wResult.add(wPartPointID);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    public List<SFCBatchBOMTaskBPM> SFC_QueryListByMessage(BMSEmployee wLoginUser, Calendar wStartTime,
                                                           Calendar wEndTime, OutResult<Integer> wErrorCode) {
        List<SFCBatchBOMTaskBPM> wResult = new ArrayList<>();
        try {
            ServiceResult<String> wInstance = this.GetDataBaseName(wLoginUser.getCompanyID(), MESDBSource.Basic,
                    wLoginUser.getID(), 0);
            wErrorCode.set(wInstance.ErrorCode);
            if (wErrorCode.Result != 0) {
                return wResult;
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);
            if (wStartTime == null) {
                wStartTime = wBaseTime;
            }
            if (wEndTime == null) {
                wEndTime = wBaseTime;
            }
            if (wStartTime.compareTo(wEndTime) > 0) {
                return wResult;
            }

            List<BFCMessage> wMessageList = CoreServiceImpl.getInstance().BFC_GetMessageListByCondition(wLoginUser,
                    wLoginUser.ID, -1, BFCMessageType.Task.getValue(),
                    StringUtils.parseListArgs(BPMEventModule.BatchOccasionNCR.getValue()), -1, -1,
                    StringUtils.parseListArgs(0, 1, 2, 3), -1, -1, wStartTime, wEndTime).List(BFCMessage.class);

            if (wMessageList == null || wMessageList.size() == 0) {
                return wResult;
            }

            List<Integer> wTaskIDList =
                    wMessageList.stream().map(p -> (int) p.MessageID).distinct().collect(Collectors.toList());

            wResult = SelectList(wLoginUser, wTaskIDList, null, null,
                    wErrorCode);
            for (SFCBatchBOMTaskBPM sfcbomTask : wResult) {
                Optional<BFCMessage> first =
                        wMessageList.stream().filter(p -> p.MessageID == sfcbomTask.ID && (p.Active == 0 || p.Active == 1 || p.Active == 2)).findFirst();
                first.ifPresent(bfcMessage -> sfcbomTask.StepID = bfcMessage.StepID);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }
}
